using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Xml;
using OpenComposite.Base.Designer;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.Designer.SCA;
using OpenComposite.EII.Interfaces;
using OpenComposite.EII.Repository;
using WeifenLuo.WinFormsUI.Docking;

namespace OpenComposite.EII.Designer
{
	public class DesignController : IDesignController, IController, IServiceProvider
	{
		#region Initialization
		public DesignController(RepositorySurfaceManager surfaceManager)
		{
			_surfaceManager = surfaceManager;

			init();

			_surface = surfaceManager.CreateControllerSurface(this);
		}
		public DesignController(RepositorySurfaceManager surfaceManager, DesignController parentController)
		{
			_parentController = parentController;
			_surfaceManager = surfaceManager;

			init();

			_surface = surfaceManager.CreateControllerSurface(this);
		}
		private void init()
		{
			_idRepository = 0;
			_idDomain = 0;
			_diagramItem = null;
			_mode = "";

			designerDockContent = null;
			designerView = null;
			_controllers = null;
			_listDesignerControlTypes = new List<Type>();

			IToolboxService tbs = this.GetService(typeof(IToolboxService)) as IToolboxService;
			if ( tbs == null ) {
				//
				// toolboxDockContent
				//
				toolboxDockContent = new ToolboxDockContent();
				toolboxDockContent.CloseButton = false;
				toolboxDockContent.Tag = 1;
			}
			_component = null;

			_verbs = new DesignerVerbCollection();
		}
		#endregion

		#region Public Members

		#region Properties
		public int RepositoryID
		{
			get { return _idRepository; }
		}
		public int DomainID
		{
			get { return _idDomain; }
		}

		public string TabText
		{
			get { return _tabText; }
			set
			{
				_tabText = value;
				if ( this.DesignerDockContent != null ) {
					this.DesignerDockContent.TabText = _tabText;
				}
			}
		}
		public string Mode
		{
			get { return _mode; }
			set
			{
				if ( _mode != value ) {
					_mode = value;
					doModeChanged();
				}
			}
		}
		public ItemType DiagramType
		{
			get { return _typeDiagram; }
		}
		public List<Type> DesignerControlTypes
		{
			get { return _listDesignerControlTypes; }
		}

		public virtual ContextMenuStrip AdditionalContextMenuStrip
		{
			get
			{
				// use default context menu
				return null;
			}
		}

		public RepositoryItemBaseEx DiagramItem
		{
			get { return _diagramItem; }
		}

		internal DesignController ParentController
		{
			get { return _parentController; }
			set { _parentController = value; }
		}

		public virtual object View
		{
			get
			{
				ViewTechnology[] views = this.SupportedTechnologies;
				if ( views == null || views.Length == 0 )
					throw new NotSupportedException("No supported view technology available.");
				return GetView(views[0]);
			}
		}
		#endregion

		#region Events
		public event EventHandler ModeChanged = null;

		public event EventHandler<CreateProcessEventArgs> CreateProcessForComponentOperation = null;
		public event EventHandler<OpenDiagramEventArgs> OpenDiagramOfRepositoryItem = null;
		#endregion

		#region Methods

		public void SetToolbox(ToolboxDockContent toolbox)
		{
			if ( toolboxDockContent != null )
				toolboxDockContent.Close();

			toolboxDockContent = toolbox;
			if ( toolboxDockContent != null ) {
				if ( toolboxDockContent.Tag is int ) {
					toolboxDockContent.Tag = ( (int)toolboxDockContent.Tag ) + 1;
				} else {
					toolboxDockContent.Tag = 1;
				}
			}
		}

		private DockPane findPane(string name, DockPanel dockPanel)
		{
			foreach ( DockPane pane in dockPanel.Panes ) {
				if ( pane.Name == name )
					return pane;
				if ( pane.CaptionText == name )
					return pane;
			}
			return null;
		}

		public XmlDocument GetXmlDocument()
		{
			return this.DesignerView.SaveDiagramToXml(DesignerControlTypes.ToArray());
		}

		public void CreateProcess(ServiceComponentSymbol component, Operation operation)
		{
			EventHandler<CreateProcessEventArgs> tmp = this.CreateProcessForComponentOperation;
			if ( tmp != null )
				tmp(this, new CreateProcessEventArgs(component, operation));
		}
		public void CreateITDesign(ServiceComponentSymbol component)
		{
			this.Save();
			Global.Data.AddRepositoryItemToDomainFolder(this.DomainID, component.RepositoryItem, ItemType.SOBA);
		}

		public void OpenDiagram(IRepositoryItem item)
		{
			EventHandler<OpenDiagramEventArgs> tmp = this.OpenDiagramOfRepositoryItem;
			if ( tmp != null ) {
				tmp(this, new OpenDiagramEventArgs(item));
			}
		}

		internal void ReloadItems(DesignerControl topControl)
		{
			if ( topControl == null )
				LoadItems();
			else
				RecursiveLoadItems(topControl);
		}

		internal virtual bool Load(RepositoryItemDesigner designer)
		{
			RepositoryItemBaseEx item = designer.RepositoryItem as RepositoryItemBaseEx;
			if ( item != null ) {
				item.Reload();
				_diagramItem = item;
				_idRepository = Global.Status.CurrentRepositoryId;
				_idDomain = Global.Status.CurrentDomainId;
				if ( item.RepositoryItemType == ItemType.SOBA || item.RepositoryItemType == ItemType.Composite ||
					 item.RepositoryItemType == ItemType.Component )
					_typeDiagram = item.RepositoryItemType;
				else
					_typeDiagram = ItemType.Business_SCA;
				this.Mode = RepositoryModes.GenericMode;
			}
			_controllers = designer.GetControllers(this);
			if ( _controllers != null && _controllers.Length > 1 ) {
				TabControl tabs = new TabControl();
				tabs.Dock = DockStyle.Fill;
				tabs.Selected += new TabControlEventHandler(tabs_Selected);
				bool firstControllerAdded = false;
				foreach ( object obj in _controllers ) {
					TabPage tab = null;
					if ( obj is DesignController ) {
						DesignController dc = (DesignController)obj;
						dc.ParentController = this;
						DesignerViewControl dvc = dc.DesignerView;
						designerView = dvc;
						dvc.Dock = DockStyle.Fill;
						tab = new TabPage();
						tab.Text = dc.TabText;
						tab.Tag = dc;
						tab.Controls.Add(dvc);
						_listDesignerControlTypes = dc.DesignerControlTypes;
						if ( !firstControllerAdded ) {
							this.ToolboxCategory = dc.ToolboxCategory;
							firstControllerAdded = true;
						}
					} else if ( obj is IRepositoryController ) {
						IRepositoryController rc = (IRepositoryController)obj;
						Control c = rc.GetView() as Control;
						if ( c != null ) {
							c.Dock = DockStyle.Fill;
							tab = new TabPage();
							tab.Text = rc.Title;
							tab.Tag = rc;
							tab.Controls.Add(c);
						}
					} else if ( obj is ContainerControl ) {
						ContainerControl cc = (ContainerControl)obj;
						cc.Dock = DockStyle.Fill;
						tab = new TabPage();
						tab.Text = cc.Text;
						tab.Tag = cc;
						tab.Controls.Add(cc);
					}
					if ( tab != null ) {
						tab.UseVisualStyleBackColor = true;
						tabs.TabPages.Add(tab);
					}
				}
				if ( designerDockContent == null ) {
					InitDockContent(tabs);
				}
			} else {
			}
			return true;
		}

		private void tabs_Selected(object sender, TabControlEventArgs e)
		{
			object obj = e.TabPage.Tag;
			if ( obj is DesignController ) {
				DesignController dc = (DesignController)obj;
				this.ToolboxCategory = dc.ToolboxCategory;
				_surfaceManager.ActiveDesignSurface = dc.Surface;
			} else if ( obj is IRepositoryController ) {
				IRepositoryController rc = (IRepositoryController)obj;
				if ( !rc.IsLoaded ) {
					rc.BeginLoad();
				}
			}
		}
		#endregion

		#endregion

		#region Protected Members

		#region Variables
		protected string _mode;
		protected ItemType _typeDiagram;

		protected int _idRepository;
		protected int _idDomain;

		protected ToolboxDockContent toolboxDockContent;
		protected DesignerViewDockContent designerDockContent;
		protected DesignerViewControl designerView;

		protected List<Type> _listDesignerControlTypes;

		protected RepositorySurfaceManager _surfaceManager;
		protected RepositoryItemBaseEx _diagramItem;
		/// <summary>
		/// Changed flag, can be set by derived types to indicate changes.
		/// </summary>
		protected bool _changed = false;

		#endregion

		#region Methods
		protected virtual void LoadDiagram()
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			DesignerControl dc = null;
			if ( _diagramItem == null )
				throw new NullReferenceException("_diagramItem == null.");

			if ( _diagramItem.Diagram == null ) {
				// create new designer control
				dc = repSvc.CreateDesignerControl(_typeDiagram, _diagramItem);
				if ( dc != null ) {
					Point loc = new Point(-this.DesignerView.MainPanel.Location.X, -this.DesignerView.MainPanel.Location.Y);
					loc.Offset(80, 50);
					if ( dc.UseGrid ) {
						// make sure it is snapped to the grid
						dc.Location = this.DesignerView.PointToGrid(loc);
					}
					this.DesignerView.AddDesignerControl(dc);
					// set designer main control
					this.DesignerView.MainControl = dc;
				}
			} else {
				// load diagram
				this.DesignerView.BeginUpdate();
				this.DesignerView.LoadDiagramFromXml(_diagramItem.Diagram, DesignerControlTypes.ToArray());
				this.DesignerView.EndUpdate();
			}
			LoadItems();
		}
		protected virtual void LoadItems()
		{
			DesignerControl[] dcArray = this.DesignerView.DesignerControls.ToArray();
			foreach ( DesignerControl dc in dcArray ) {
				RecursiveLoadItems(dc);
			}
		}
		protected virtual void RecursiveLoadItems(DesignerControl dcCurrent)
		{
			if ( dcCurrent is IRepositoryItemSymbol ) {
				( (IRepositoryItemSymbol)dcCurrent ).Load(_idRepository, _idDomain);
			}
			DesignerControl[] dcArray = dcCurrent.Controls.ToArray();
			foreach ( DesignerControl dc in dcArray ) {
				RecursiveLoadItems(dc);
			}
		}

		protected virtual void SaveItems(List<DesignerControl> oldHierarchy)
		{
			RepositoryItemBase itemParent = _diagramItem;
			if ( itemParent == null )
				throw new Exception("No parent item available.");

			foreach ( DesignerControl dc in oldHierarchy ) {
				DeleteHierarchyRecursive(dc);
			}

			DesignerControl[] dcArray = this.DesignerView.DesignerControls.ToArray();
			foreach ( DesignerControl dc in dcArray ) {
				if ( dc != this.DesignerView.MainControl ) {
					RecursiveSaveItems(dc, itemParent);
				} else {
					RecursiveSaveItems(dc, null);
				}
			}
		}
		protected void DeleteHierarchyRecursive(DesignerControl dcCurrent)
		{
			IRepositoryItemSymbol parent = dcCurrent as IRepositoryItemSymbol;
			if ( parent != null && !parent.IsReference ) {
				RepositoryItemBaseEx itemex = parent.RepositoryItem as RepositoryItemBaseEx;
				if ( itemex == null ||
					 ( itemex.CreatedType & CreatedTypeFlags.RecursiveDeleteAllowed )
						== CreatedTypeFlags.RecursiveDeleteAllowed ) {
					if ( parent.RepositoryItem != null )
						Global.Data.DeleteRepositoryChildHierarchy(parent.RepositoryItem);
					DesignerControl[] dcArray = dcCurrent.Controls.ToArray();
					foreach ( DesignerControl dctrl in dcArray ) {
						DeleteHierarchyRecursive(dctrl);
					}
				}
			} else if ( parent == null ) {
				DesignerControl[] dcArray = dcCurrent.Controls.ToArray();
				foreach ( DesignerControl dctrl in dcArray ) {
					DeleteHierarchyRecursive(dctrl);
				}
			}
		}
		protected virtual void RecursiveSaveItems(DesignerControl dcCurrent, IRepositoryItem itemParent)
		{
			IRepositoryItem currentItem = null;
			if ( itemParent != null ) {
				RepositoryService repSvc = (RepositoryService)_surfaceManager.GetService(typeof(RepositoryService));
				if ( dcCurrent is IRepositoryItemSymbol ) {
					IRepositoryItemSymbol ris = (IRepositoryItemSymbol)dcCurrent;
					ris.Save(_idRepository, _idDomain);
					if ( ris.RepositoryItem != null && ris.SaveHierarchy ) {
						DataTable dt = Global.Data.GetRepositoryParentsOfType(
							ris.RepositoryItem.RepositoryItemType, ris.RepositoryItem.ID,
							ItemType.GenericFolder);
						if ( dt.Rows.Count == 0 ) {
							DataTable dtParent = Global.Data.GetRepositoryParentsOfType(
								itemParent.RepositoryItemType, itemParent.ID,
								ItemType.GenericFolder);
							if ( dtParent.Rows.Count == 0 )
								// add to domain folder
								Global.Data.AddRepositoryItemToDomainFolder(_idDomain, ris.RepositoryItem);
							else {
								GenericFolder folder = repSvc.GetItem(
									(ItemType)dtParent.Rows[0]["parent_reptype_id"],
									(int)dtParent.Rows[0]["parent_id"],
									true) as GenericFolder;
								if ( folder != null &&
									 folder.AllowedChildTypes.Contains(ris.RepositoryItem.RepositoryItemType) ) {
									// add to parent folder
									Global.Data.AddRepositoryHierarchy(
										(ItemType)dtParent.Rows[0]["parent_reptype_id"],
										(int)dtParent.Rows[0]["parent_id"],
										ris.RepositoryItem.RepositoryItemType,
										ris.RepositoryItem.ID,
										ris.RepositoryItem.Display,
										_idRepository);
								} else {
									// add to domain folder
									Global.Data.AddRepositoryItemToDomainFolder(_idDomain, ris.RepositoryItem);
								}
							}
						}
						Global.Data.AddRepositoryHierarchy(itemParent, ris.RepositoryItem, _idRepository);
						currentItem = ris.RepositoryItem;
					}
				} else {
					currentItem = itemParent;
				}
			} else if ( dcCurrent is IRepositoryItemSymbol ) {
				currentItem = ( (IRepositoryItemSymbol)dcCurrent ).RepositoryItem;
			}
			if ( currentItem != null ) {
				DesignerControl[] dcArray = dcCurrent.Controls.ToArray();
				foreach ( DesignerControl dc in dcArray ) {
					RecursiveSaveItems(dc, currentItem);
				}
			}
		}

		protected virtual void OnLoaded()
		{
			EventHandler tmp = this.Loaded;
			if ( tmp != null )
				tmp(this, EventArgs.Empty);
		}
		protected virtual void OnSaved()
		{
			_changed = false;
			EventHandler tmp = this.Saved;
			if ( tmp != null ) {
				tmp(this, EventArgs.Empty);
			}
		}
		protected virtual void OnClosing(FormClosingEventArgs e)
		{
			CancelEventHandler tmp = this.Closing;
			if ( tmp != null ) {
				tmp(this, e);
			}
		}
		protected virtual void OnClosed()
		{
			if ( _controllers != null ) {
				foreach ( object obj in _controllers ) {
					if ( obj is DesignController ) {
						DesignController dc = (DesignController)obj;
						dc.Close();
					} else if ( obj is IRepositoryController ) {
						IRepositoryController rc = (IRepositoryController)obj;
						rc.BeginUnload();
					} else if ( obj is ContainerControl ) {
						ContainerControl cc = (ContainerControl)obj;
						cc.Dispose();
						cc = null;
					}
				}
				_controllers = null;
			}
			EventHandler tmp = this.Closed;
			if ( tmp != null ) {
				tmp(this, EventArgs.Empty);
			}
		}

		protected virtual void OnModeChanged()
		{
			EventHandler tmp = this.ModeChanged;
			if ( tmp != null )
				tmp(this, EventArgs.Empty);
		}

		protected virtual void OnDragDrop(DragEventArgs e)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			if ( e.Data.GetDataPresent(typeof(DesignerControl)) ) {
				DesignerControl ctrl = e.Data.GetData(typeof(DesignerControl)) as DesignerControl;
				if ( ctrl != null ) {
					if ( ctrl.UseGrid )
						ctrl.Location = this.DesignerView.PointToGrid(this.DesignerView.PointToClient(
							new Point(e.X, e.Y)));
					else
						ctrl.Location = this.DesignerView.PointToClient(new Point(e.X, e.Y));
					//addRepositoryItemToMainControlParent(ctrl);
					this.DesignerView.BeginUpdate();
					this.DesignerView.DropObject(ctrl, ctrl.Location, MouseButtons.Left);
					this.DesignerView.EndUpdate();
				}
			} else if ( e.Data.GetDataPresent(typeof(ItemType)) ) {
				ItemType type = (ItemType)e.Data.GetData(typeof(ItemType));
				bool bShowInputDlg = !( type == ItemType.SCA_Export || type == ItemType.SCA_Import ||
										type == ItemType.Selector );
				DesignerControl ctrl = repSvc.CreateDesignerControl(type, bShowInputDlg);
				if ( ctrl != null ) {
					IRepositoryItemSymbol ris = ctrl as IRepositoryItemSymbol;
					RepositoryItemBaseEx itemex = ris.RepositoryItem as RepositoryItemBaseEx;
					if ( type == ItemType.Workflow && ris != null ) {
						if ( itemex != null ) {
							Global.Data.AddRepositoryItemToDomainFolder(itemex.DomainId, itemex);
						} else {
							Global.Data.AddRepositoryItemToDomainFolder(Global.Status.CurrentDomainId, ris.RepositoryItem);
						}
					}
					if ( ctrl.UseGrid ) {
						ctrl.Location = this.DesignerView.PointToGrid(this.DesignerView.PointToClient(
							new Point(e.X, e.Y)));
					} else {
						ctrl.Location = this.DesignerView.PointToClient(new Point(e.X, e.Y));
					}
					//addRepositoryItemToMainControlParent(ctrl);
					this.DesignerView.BeginUpdate();
					this.DesignerView.DropObject(ctrl, ctrl.Location, MouseButtons.Left);
					this.DesignerView.EndUpdate();
				}
			} else if ( e.Data.GetDataPresent(typeof(RepositoryItemBase)) ) {
				RepositoryItemBase item = (RepositoryItemBase)e.Data.GetData(typeof(RepositoryItemBase));
				DesignerControl ctrl = repSvc.CreateDesignerControl(item);
				if ( ctrl != null ) {
					if ( ctrl.UseGrid )
						ctrl.Location = this.DesignerView.PointToGrid(this.DesignerView.PointToClient(
							new Point(e.X, e.Y)));
					else
						ctrl.Location = this.DesignerView.PointToClient(new Point(e.X, e.Y));
					//addRepositoryItemToMainControlParent(ctrl);
					this.DesignerView.BeginUpdate();
					this.DesignerView.DropObject(ctrl, ctrl.Location, MouseButtons.Left);
					this.DesignerView.EndUpdate();
				} else {
					this.DesignerView.BeginUpdate();
					this.DesignerView.DropObject(item,
						this.DesignerView.PointToClient(new Point(e.X, e.Y)), MouseButtons.Left);
					this.DesignerView.EndUpdate();
				}
			} else if ( e.Data.GetDataPresent(typeof(RepositoryItemDragDropContainer)) ) {
				RepositoryItemDragDropContainer ddcont = (RepositoryItemDragDropContainer)e.Data.GetData(typeof(RepositoryItemDragDropContainer));
				RepositoryItemBase item = ddcont.Item;
				DesignerControl ctrl = null;

				if ( ddcont.CreateDesignerControl )
					ctrl = repSvc.CreateDesignerControl(item);

				if ( ctrl != null ) {
					if ( ctrl.UseGrid )
						ctrl.Location = this.DesignerView.PointToGrid(this.DesignerView.PointToClient(
							new Point(e.X, e.Y)));
					else
						ctrl.Location = this.DesignerView.PointToClient(new Point(e.X, e.Y));
					//addRepositoryItemToMainControlParent(ctrl);
					this.DesignerView.BeginUpdate();
					this.DesignerView.DropObject(ctrl, ctrl.Location, MouseButtons.Left);
					this.DesignerView.EndUpdate();
				} else {
					this.DesignerView.BeginUpdate();
					this.DesignerView.DropObject(item,
						this.DesignerView.PointToClient(new Point(e.X, e.Y)), MouseButtons.Left);
					this.DesignerView.EndUpdate();
				}
			} else if ( e.Data.GetDataPresent(typeof(TreeNode)) ) {
				RepositoryItemBase item = ( (TreeNode)e.Data.GetData(typeof(TreeNode)) ).Tag as RepositoryItemBase;
				if ( item != null ) {
					this.DesignerView.BeginUpdate();
					Point loc = this.DesignerView.PointToClient(new Point(e.X, e.Y));
					this.DesignerView.DropObject(item, loc, MouseButtons.Left);
					this.DesignerView.EndUpdate();
				}
			}
		}

		/// <summary>
		/// Initialize the DockContent window.
		/// Steps:
		///  - if DesignerView is not initialized call InitView
		///  - create new DesignerViewDockContent with the DesignerView
		///  - register FormClosed / Closing events
		///  - register Save and ShowXml events
		/// </summary>
		protected virtual void InitDockContent(Control view)
		{
			if ( view == null ) {
				if ( designerView == null ) {
					InitView();
				} else {
					view = designerView;
				}
			}
			designerDockContent = new DesignerViewDockContent(this, view);
			designerDockContent.TabText = this.TabText;
			// form close events
			designerDockContent.FormClosed += new FormClosedEventHandler(_formDesigner_FormClosed);
			designerDockContent.FormClosing += new FormClosingEventHandler(_formDesigner_FormClosing);
			// toolbar
			designerDockContent.Save += new EventHandler(_formDesigner_Save);
			designerDockContent.ShowXml += new EventHandler(_formDesigner_ShowXml);
			designerDockContent.Activated += new EventHandler(designerDockContent_Activated);
		}

		void designerDockContent_Activated(object sender, EventArgs e)
		{
			_surfaceManager.ActiveDesignSurface = _surface;
		}
		/// <summary>
		/// Initialize the View control.
		/// Steps:
		///  - set DesignController and DesignerSite
		///  - register Drag'n'Drop events
		/// </summary>
		protected virtual void InitView()
		{
			if ( designerDockContent != null && designerDockContent.DesignerView != null ) {
				return; // view was initialized by designerDockContent
			}
			designerView = new DesignerViewControl();

			designerView.DesignController = this;
			designerView.DesignerSite = new DesignerSite(_surfaceManager, designerView, designerView.Container);
			// drag & drop
			designerView.MainPanel.DragDrop += new DragEventHandler(DesignerPanel_DragDrop);
			designerView.MainPanel.DragEnter += new DragEventHandler(DesignerPanel_DragEnter);
			designerView.MainPanel.DragLeave += new EventHandler(DesignerPanel_DragLeave);
			designerView.MainPanel.DragOver += new DragEventHandler(DesignerPanel_DragOver);
			designerView.MainPanel.GiveFeedback += new GiveFeedbackEventHandler(DesignerPanel_GiveFeedback);
			designerView.MainPanel.QueryContinueDrag += new QueryContinueDragEventHandler(DesignerPanel_QueryContinueDrag);
			designerView.ShowDebugInfo += new EventHandler<ObjectEventArgs>(designerView_ShowDebugInfo);
		}

		void designerView_ShowDebugInfo(object sender, ObjectEventArgs e)
		{
			DesignerViewControl.SelectedDesignerControlCollection coll = e.Argument as DesignerViewControl.SelectedDesignerControlCollection;
			Helpers.OpenDebugViewer(coll[0]);
		}

		#endregion

		#endregion

		#region Private Members

		#region Fields
		private string _tabText = "";
		private DesignerVerbCollection _verbs;
		private IComponent _component;
		private object[] _controllers;
		private DesignController _parentController;
		private DesignerControl _dcCurrentDrag = null;
		private RepositorySurface _surface = null;
		#endregion

		#region Methods

		private void addRepositoryItemToMainControlParent(DesignerControl ctrl)
		{
			if ( !( ctrl is IRepositoryItemSymbol ) && _diagramItem != null )
				return;

			IRepositoryItemSymbol ris = (IRepositoryItemSymbol)ctrl;
			DataTable dtParents = Global.Data.GetRepositoryHierarchyParents(_diagramItem);
			if ( ris.RepositoryItem != null && dtParents != null && dtParents.Rows.Count > 0 ) {
				foreach ( DataRow row in dtParents.Rows ) {
					Global.Data.AddRepositoryHierarchy(
						(ItemType)row["parent_reptype_id"], (int)row["parent_id"],
						ris.RepositoryItem.RepositoryItemType, ris.RepositoryItem.ID,
						ris.RepositoryItem.Display,
						(int)row["repository_id"]);
				}
			}
		}

		private void doModeChanged()
		{
			OnModeChanged();
		}
		#endregion

		#region Event Handlers
		private void _formDesigner_FormClosed(object sender, FormClosedEventArgs e)
		{
			if ( toolboxDockContent != null ) {
				if ( toolboxDockContent.Tag is int ) {
					toolboxDockContent.Tag = ( (int)toolboxDockContent.Tag ) - 1;
				} else {
					toolboxDockContent.Tag = 0;
				}
				if ( (int)toolboxDockContent.Tag <= 0 )
					toolboxDockContent.Close();
			}
			OnClosed();
		}
		private void _formDesigner_FormClosing(object sender, FormClosingEventArgs e)
		{
			if ( _diagramItem != null ) {
				OnClosing(e);
				if ( e.Cancel )
					return;
				XmlDocument xdNew = this.GetXmlDocument();
				if ( _changed || ( _diagramItem.Diagram != null &&
					 xdNew.DocumentElement.InnerXml != _diagramItem.Diagram.DocumentElement.InnerXml ) ) {
					// diagram changed
					DialogResult result = MessageBox.Show(
						string.Format(Resources.msgSaveChangesDiagram, _diagramItem.Name, Environment.NewLine),
						designerDockContent.TabText, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
					if ( result == DialogResult.Yes ) {
						this.Save();
						e.Cancel = false;
					} else if ( result == DialogResult.No ) {
						e.Cancel = false;
					} else {
						e.Cancel = true;
					}
				}
			}
		}

		private void DesignerPanel_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
		{
			if ( e.Action != DragAction.Continue ) {
				_dcCurrentDrag = null;
			}
		}
		private void DesignerPanel_GiveFeedback(object sender, GiveFeedbackEventArgs e)
		{
		}
		private void DesignerPanel_DragOver(object sender, DragEventArgs e)
		{
			DesignerViewPanel designerPanel = sender as DesignerViewPanel;
			if ( designerPanel == null ) designerPanel = this.DesignerPanel;

			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			if ( e.Data.GetDataPresent(typeof(ItemType)) ) {
				ItemType itemtype = (ItemType)e.Data.GetData(typeof(ItemType));
				Type type = repSvc.GetDesignerControlType(itemtype);
				Point location = new Point(e.X, e.Y);
				location = designerPanel.PointToClient(location);
				if ( this.DesignerControlTypes.Contains(type) &&
					 this.DesignerView.IsDropAllowed(type, location, MouseButtons.Left) ) {
					e.Effect = DragDropEffects.Move;
				} else
					e.Effect = DragDropEffects.None;
			} else if ( e.Data.GetDataPresent(typeof(TreeNode)) ) {
				RepositoryItemBase item = ( (TreeNode)e.Data.GetData(typeof(TreeNode)) ).Tag as RepositoryItemBase;
				Point location = new Point(e.X, e.Y);
				location = designerPanel.PointToClient(location);
				if ( item != null ) {
					if ( this.DesignerView.IsDropAllowed(item, location, MouseButtons.Left) ) {
						e.Effect = DragDropEffects.Link;
					} else {
						if ( _dcCurrentDrag == null ) {
							_dcCurrentDrag = repSvc.CreateDesignerControl(item);
						}
						if ( _dcCurrentDrag != null && this.DesignerView.IsDropAllowed(_dcCurrentDrag, location, MouseButtons.Left) ) {
							e.Effect = DragDropEffects.Link;
							RepositoryItemDragDropContainer cont = new RepositoryItemDragDropContainer(item, true);
							e.Data.SetData(cont);
						} else {
							e.Effect = DragDropEffects.None;
						}
					}
				} else {
					e.Effect = DragDropEffects.None;
				}
			} else if ( e.Data.GetDataPresent(typeof(RepositoryItemBase)) ) {
				RepositoryItemBase item = (RepositoryItemBase)e.Data.GetData(typeof(RepositoryItemBase));
				Point location = new Point(e.X, e.Y);
				location = designerPanel.PointToClient(location);
				if ( item != null &&
					 this.DesignerView.IsDropAllowed(item, location, MouseButtons.Left) ) {
					e.Effect = DragDropEffects.Link;
				} else {
					e.Effect = DragDropEffects.None;
				}
			} else if ( e.Data.GetDataPresent(typeof(RepositoryItemDragDropContainer)) ) {
				RepositoryItemBase item = ( (RepositoryItemDragDropContainer)e.Data.GetData(typeof(RepositoryItemDragDropContainer)) ).Item;
				Point location = new Point(e.X, e.Y);
				location = designerPanel.PointToClient(location);
				if ( item != null &&
					 this.DesignerView.IsDropAllowed(item, location, MouseButtons.Left) ) {
					e.Effect = DragDropEffects.Link;
				} else {
					e.Effect = DragDropEffects.None;
				}
			} else if ( e.Data.GetDataPresent(typeof(Row)) ) {
				Row row = (Row)e.Data.GetData(typeof(Row));
				//if ( row != null && row.ListView != null ) {
				//    row.ListView.Refresh();
				//}
				//Point location = new Point(e.X, e.Y);
				//location = designerPanel.PointToClient(location);
				//if ( this.DesignerView.IsDropAllowed(row, location, MouseButtons.Right) ) {
				//    e.Effect = e.AllowedEffect;
				//} else {
				//    e.Effect = DragDropEffects.None;
				//}

			}
			//foreach ( Type type in this.DesignerControlTypes ) {
			//    if ( !e.Data.GetDataPresent(type) )
			//        continue;
			//    object obj = e.Data.GetData(type);
			//    if ( obj is DesignerControl ) {
			//        e.Effect = DragDropEffects.Link;
			//    }
			//}
		}
		private void DesignerPanel_DragLeave(object sender, EventArgs e)
		{
			_dcCurrentDrag = null;
		}
		private void DesignerPanel_DragEnter(object sender, DragEventArgs e)
		{
		}
		private void DesignerPanel_DragDrop(object sender, DragEventArgs e)
		{
			_dcCurrentDrag = null;
			OnDragDrop(e);
		}

		private void _formDesigner_ShowXml(object sender, EventArgs e)
		{
			try {
				XmlDocument xd = this.GetXmlDocument();
				formXmlViewer viewer = new formXmlViewer();
				viewer.XmlDocument = xd;
				viewer.ShowDialog();
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.DesignerDockContent.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		private void _formDesigner_Save(object sender, EventArgs e)
		{
			Save();
		}
		#endregion

		#endregion

		#region IController Members

		public event EventHandler Loaded = null;
		public event EventHandler Saved = null;
		public event CancelEventHandler Closing = null;
		public event EventHandler Closed = null;

		public virtual void Show(DockPanel dockPanel)
		{
			DockPane pane = findPane("Domain Gap Analysis", dockPanel);
			if ( toolboxDockContent != null ) {
				DockPane paneToolboxes = findPane("paneToolboxes", dockPanel);
				toolboxDockContent.Enabled = true;
				toolboxDockContent.Toolbox.Enabled = true;
				toolboxDockContent.ShowHint = DockState.DockLeft;
				if ( paneToolboxes != null )
					toolboxDockContent.Show(paneToolboxes, null);
				else if ( pane != null ) {
					toolboxDockContent.DockPanel = dockPanel;
					DockPane dp = dockPanel.DockPaneFactory.CreateDockPane(toolboxDockContent, pane, DockAlignment.Bottom, 0.4, true);
					dp.Name = "paneToolboxes";
					toolboxDockContent.Show(dp, null);
				} else {
					toolboxDockContent.DockPanel = dockPanel;
					DockPane dp = dockPanel.DockPaneFactory.CreateDockPane(toolboxDockContent, DockState.DockLeft, true);
					dp.Name = "paneToolboxes";
					toolboxDockContent.Show(dp, null);
				}
			}
			if ( designerDockContent == null ) {
				InitDockContent(null);
			}
			//_formToolbox.Show(pane, DockAlignment.Bottom, 0.4);
			if ( this.DiagramItem != null ) {
				designerDockContent.TabText = this.DiagramItem.Name;
				designerDockContent.Icon = this.DiagramItem.GetIcon();
				dockPanel.ShowDocumentIcon = true;
			}
			designerDockContent.Show(dockPanel);
			if ( designerDockContent.DesignerView != null ) {
				designerDockContent.DesignerView.Types = DesignerControlTypes.ToArray();
			} else if ( designerView != null ) {
				designerView.Types = DesignerControlTypes.ToArray();
			}
		}
		public void Close()
		{
			if ( designerDockContent != null ) {
				designerDockContent.Close();
			}
			OnClosed();

			try {
				if ( designerDockContent != null ) {
					designerDockContent.Dispose();
					designerDockContent = null;
				}
				if ( designerView != null ) {
					designerView.Dispose();
					designerView = null;
				}
				if ( toolboxDockContent != null ) {
					toolboxDockContent.Dispose();
					toolboxDockContent = null;
				}
			} catch {
			}
		}

		public virtual bool Load(RepositoryItemBaseEx item, int repositoryId, int domainId)
		{
			item.Reload();
			_diagramItem = item;
			_idRepository = repositoryId;
			_idDomain = domainId;
			if ( item.RepositoryItemType == ItemType.SOBA || item.RepositoryItemType == ItemType.Composite ||
				 item.RepositoryItemType == ItemType.Component )
				_typeDiagram = item.RepositoryItemType;
			else
				_typeDiagram = ItemType.Business_SCA;
			this.Mode = RepositoryModes.GenericMode;

			LoadDiagram();

			OnLoaded();

			return true;
		}
		public virtual bool Load(ItemType diagramType, RepositoryItemBaseEx item, int repositoryId, int domainId)
		{
			item.Reload();
			_diagramItem = item;
			_idRepository = repositoryId;
			_idDomain = domainId;
			_typeDiagram = ItemType.SOBA;
			if ( diagramType == ItemType.SOBA )
				this.Mode = RepositoryModes.ITMode;
			else
				this.Mode = RepositoryModes.BusinessMode;

			LoadDiagram();

			OnLoaded();

			return true;
		}

		public virtual bool Save()
		{
			if ( _diagramItem == null ) return false; // EXIT

			Cursor.Current = Cursors.WaitCursor;
			try {

				List<DesignerControl> oldHierarchy = null;
				bool saved = false;
				// save diagram main item
				if ( this.DesignerView.MainControl != null &&
					 this.DesignerView.MainControl is IRepositoryItemSymbol ) {
					RepositoryItemBaseEx mainitem =
						( (IRepositoryItemSymbol)this.DesignerView.MainControl )
							.RepositoryItem as RepositoryItemBaseEx;
					if ( mainitem != null ) {
						oldHierarchy = this.DesignerView.LoadDiagramFromXmlAndGetTopControlsHierarchyOnly(
							mainitem.Diagram, this.DesignerView.Types);
						mainitem.Diagram = this.GetXmlDocument();
						saved = ( (IRepositoryItemSymbol)this.DesignerView.MainControl ).Save(_idRepository, _idDomain);
					}
				}
				if ( !saved && _diagramItem != null ) {
					oldHierarchy = this.DesignerView.LoadDiagramFromXmlAndGetTopControlsHierarchyOnly(
						_diagramItem.Diagram, this.DesignerView.Types);
					_diagramItem.Diagram = this.GetXmlDocument();
					_diagramItem.Save();
				}
				// save other diagram items
				SaveItems(oldHierarchy);

				OnSaved();
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.TabText, MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			} finally {
				Cursor.Current = Cursors.Default;
			}
			if ( DesignerDockContent != null ) {
				this.DesignerDockContent.Activate();
			}

			return true;
		}

		public RepositoryItemBase RepositoryItem
		{
			get { return this.DiagramItem; }
		}

		public ItemType ControllerType
		{
			get { return this.DiagramType; }
		}

		public virtual string ToolboxCategory { get; set; }
		public virtual IRepositoryToolbox Toolbox
		{
			get
			{
				IRepositoryToolbox rt = this.GetService(typeof(IToolboxService)) as IRepositoryToolbox;
				if ( rt != null ) {
					return rt;
				} else if ( this.ParentController != null ) {
					return this.ParentController.Toolbox;
				} else {
					return toolboxDockContent;
				}
			}
		}
		public virtual DesignerViewDockContent DesignerDockContent
		{
			get
			{
				if ( this.ParentController != null ) {
					return this.ParentController.DesignerDockContent;
				} else {
					return designerDockContent;
				}
			}
		}
		public virtual DesignerViewControl DesignerView
		{
			get
			{
				if ( designerView == null ) {
					InitView();
				}
				designerView.Types = DesignerControlTypes.ToArray();
				return designerView;
			}
		}
		public virtual DesignerViewPanel DesignerPanel
		{
			get
			{
				if ( designerDockContent != null ) {
					return designerDockContent.DesignerPanel;
				} else if ( designerView != null ) {
					return designerView.MainPanel;
				} else {
					return null;
				}
			}
		}
		public virtual ToolStrip ToolStrip
		{
			get
			{
				if ( this.ParentController != null ) {
					return this.ParentController.ToolStrip;
				} else if ( this.DesignerDockContent != null ) {
					return this.DesignerDockContent.ToolStrip;
				} else {
					return null;
				}
			}
		}

		public virtual RepositorySurface Surface
		{
			get { return _surface; }
		}
		#endregion

		#region IServiceProvider Members

		public object GetService(Type serviceType)
		{
			object service = null;
			if ( _surfaceManager != null ) {
				service = _surfaceManager.GetService(serviceType);
			}
			if ( service == null && _surface != null ) {
				service = _surface.GetService(serviceType);
			}
			if ( service == null && _parentController != null ) {
				service = _parentController.GetService(serviceType);
			}
			if ( service == null && _diagramItem != null ) {
				service = _diagramItem.GetService(serviceType);
			}
			return service;
		}

		#endregion

		#region IDesignController Members

		public virtual Route CreateNewRoute(DesignerControl start, DesignerControl end)
		{
			return new Route();
		}

		#endregion

		#region IRootDesigner Members

		public virtual object GetView(ViewTechnology technology)
		{
			if ( technology != ViewTechnology.Default ) {
				throw new ArgumentException("Not a supported view technology", "technology");
			}
			if ( designerView == null ) {
				InitView();
			}
			designerView.Types = DesignerControlTypes.ToArray();
			return designerView;
		}

		public virtual ViewTechnology[] SupportedTechnologies
		{
			get { return new ViewTechnology[] { ViewTechnology.Default }; }
		}

		#endregion

		#region IDesigner Members

		public virtual System.ComponentModel.IComponent Component
		{
			get { return _component; }
		}

		public virtual void DoDefaultAction()
		{
		}

		public virtual void Initialize(System.ComponentModel.IComponent component)
		{
			_component = component;
		}

		public virtual System.ComponentModel.Design.DesignerVerbCollection Verbs
		{
			get { return _verbs; }
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
		}

		#endregion
	}

	#region Class: ToolboxDockContent , BaseClass: DockContent
	//public class ToolboxDockContent : DockContent
	//{
	//    #region Initialization
	//    public ToolboxDockContent()
	//    {
	//        init();
	//    }
	//    private void init()
	//    {
	//        //
	//        // init this
	//        //
	//        this.TabText = "Toolbox";
	//        this.DockableAreas = DockAreas.Float | DockAreas.DockBottom | DockAreas.DockLeft |
	//                           DockAreas.DockRight | DockAreas.DockTop;
	//        this.ShowHint = DockState.DockLeftAutoHide;
	//        this.Size = new Size(50, 200);
	//        this.AutoHidePortion = .1;
	//        this.Icon = Resources.toolbox_16;

	//        //
	//        // init _toolstrip
	//        //
	//        _toolstrip = new ToolStrip();
	//        _toolstrip.Renderer = new ToolBoxRenderer();
	//        _toolstrip.GripStyle = ToolStripGripStyle.Hidden;
	//        _toolstrip.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
	//        _toolstrip.Items.Clear();
	//        _toolstrip.Enabled = false;
	//        _toolstrip.Visible = true;
	//        _toolstrip.Dock = DockStyle.Top;

	//        this.Controls.Add(_toolstrip);
	//    }
	//    #endregion

	//    #region Variables
	//    private ToolStrip _toolstrip;
	//    #endregion

	//    #region Properties
	//    public ToolStrip ToolStrip
	//    {
	//        get { return _toolstrip; }
	//    }
	//    #endregion

	//    #region Methods
	//    public void AddItem(ToolStripItem item)
	//    {
	//        this.ToolStrip.Items.Add(item);
	//    }
	//    public void ClearItems()
	//    {
	//        this.ToolStrip.Items.Clear();
	//    }
	//    #endregion

	//}
	#endregion

	#region Class: DesignerViewDockContent , BaseClass: DockContent
	//public class DesignerViewDockContent : DockContent
	//{
	//    #region Initialization
	//    public DesignerViewDockContent()
	//    {
	//        init();
	//    }
	//    private void init()
	//    {
	//        //
	//        // init this
	//        //
	//        this.TabText = "Designer";
	//        this.DockableAreas = DockAreas.Document;
	//        this.ShowHint = DockState.Document;

	//        //
	//        // init _ctrlDesigner
	//        //
	//        _ctrlDesigner = new DesignerViewControl();
	//        _ctrlDesigner.Dock = DockStyle.Fill;

	//        this.Controls.Add(_ctrlDesigner);
	//    }
	//    #endregion

	//    #region Variables
	//    private DesignerViewControl _ctrlDesigner;
	//    #endregion

	//    #region Properties
	//    public DesignerViewControl DesignerView
	//    {
	//        get { return _ctrlDesigner; }
	//    }
	//    #endregion

	//    #region Methods
	//    #endregion

	//}
	#endregion

	#region Class: CreateProcessEventArgs , BaseClass: EventArgs
	public class CreateProcessEventArgs : EventArgs
	{
		#region Initialization
		public CreateProcessEventArgs(ServiceComponentSymbol component, Operation operation)
		{
			_component = component;
			_operation = operation;
		}
		#endregion

		#region Properties
		private readonly ServiceComponentSymbol _component;
		public ServiceComponentSymbol ComponentSymbol
		{
			get { return _component; }
		}
		private Operation _operation;
		public Operation Operation
		{
			get { return _operation; }
		}
		#endregion
	}
	#endregion

	#region Class: OpenDiagramEventArgs , BaseClass: EventArgs
	public class OpenDiagramEventArgs : EventArgs
	{
		#region Initialization
		public OpenDiagramEventArgs(IRepositoryItem item)
		{
			_item = item;
		}
		#endregion

		#region Properties
		private readonly IRepositoryItem _item;
		public IRepositoryItem Item
		{
			get { return _item; }
		}
		#endregion
	}
	#endregion
}
